import { useCallback, useRef, useState } from 'react';
import {
  ReactFlow,
  useNodesState,
  useEdgesState,
  addEdge,
  Controls,
  Background,
  Connection,
  Edge,
  Node,
  ReactFlowProvider,
  useReactFlow,
  BackgroundVariant,
  ConnectionLineType,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';

import { WorkflowSidebar } from './WorkflowSidebar';
import { PropertiesPanel } from './PropertiesPanel';
import { TestingPanel } from './TestingPanel';
import { CompactNode } from './nodes/CompactNode';
import { N8nStyleNode } from './nodes/N8nStyleNode';
import { MirrorAgent } from './MirrorAgent';
import { Button } from '@/components/ui/button';
import { 
  Plus, 
  Save, 
  Download, 
  Upload, 
  Settings, 
  PlayCircle, 
  TestTube,
  Sparkles
} from 'lucide-react';
import { useToast } from '@/hooks/use-toast';
import { importN8nWorkflow, exportToN8nFormat } from './utils/n8nImporter';

const nodeTypes = {
  // All types use the n8n style node
  'multiple-choice': N8nStyleNode,
  'word-cloud': N8nStyleNode,
  'open-ended': N8nStyleNode,
  'scales': N8nStyleNode,
  'ranking': N8nStyleNode,
  'qa': N8nStyleNode,
  'pin-on-image': N8nStyleNode,
  'select-answer': N8nStyleNode,
  'type-answer': N8nStyleNode,
  'text': N8nStyleNode,
  'image': N8nStyleNode,
  'video': N8nStyleNode,
  'instructions': N8nStyleNode,
  'google-slides': N8nStyleNode,
  'powerpoint': N8nStyleNode,
  'miro': N8nStyleNode,
};

const initialNodes: Node[] = [
  {
    id: '1',
    type: 'text',
    position: { x: 250, y: 150 },
    data: { 
      label: 'Welcome Text',
      subtitle: 'Introduction Content',
      icon: 'FileText',
      category: 'content'
    },
  },
];

const initialEdges: Edge[] = [];

function WorkflowCanvasInner() {
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
  const { screenToFlowPosition } = useReactFlow();
  const { toast } = useToast();
  const [isRunning, setIsRunning] = useState(false);
  const [selectedNode, setSelectedNode] = useState<any>(null);
  const [showTesting, setShowTesting] = useState(false);
  const [isDragOver, setIsDragOver] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const onConnect = useCallback(
    (params: Connection) => setEdges((eds) => addEdge(params, eds)),
    [setEdges]
  );

  const onDragOver = useCallback((event: React.DragEvent) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
    setIsDragOver(true);
  }, []);

  const onDragLeave = useCallback((event: React.DragEvent) => {
    // Only set to false if we're leaving the canvas area completely
    if (!event.currentTarget.contains(event.relatedTarget as Element | null)) {
      setIsDragOver(false);
    }
  }, []);

  const onDrop = useCallback(
    (event: React.DragEvent) => {
      event.preventDefault();
      setIsDragOver(false);

      const type = event.dataTransfer.getData('application/reactflow');
      const nodeData = JSON.parse(event.dataTransfer.getData('application/nodedata'));

      if (typeof type === 'undefined' || !type) {
        return;
      }

      const position = screenToFlowPosition({
        x: event.clientX,
        y: event.clientY,
      });

      const newNode: Node = {
        id: `${type}-${Date.now()}`,
        type,
        position,
        data: nodeData,
      };

      setNodes((nds) => nds.concat(newNode));
      
      // Show success feedback
      toast({
        title: "Node Added",
        description: `${nodeData.label} has been added to your flow.`,
      });
    },
    [screenToFlowPosition, setNodes, toast]
  );

  const onNodeClick = useCallback((event: React.MouseEvent, node: Node) => {
    setSelectedNode({
      id: node.id,
      type: node.type,
      ...node.data,
    });
  }, []);

  const updateNodeData = useCallback((nodeId: string, data: Partial<any>) => {
    setNodes((nds) =>
      nds.map((node) =>
        node.id === nodeId
          ? { ...node, data: { ...node.data, ...data } }
          : node
      )
    );
  }, [setNodes]);

  const runWorkflow = async () => {
    setIsRunning(true);
    
    // Simulate presentation mode
    toast({
      title: "Presentation Started",
      description: "Your courseware is now in presentation mode...",
    });

    setTimeout(() => {
      setIsRunning(false);
      toast({
        title: "Presentation Complete",
        description: "Courseware presentation finished successfully!",
      });
    }, 3000);
  };

  const saveWorkflow = () => {
    const workflow = { nodes, edges };
    localStorage.setItem('workflow', JSON.stringify(workflow));
    toast({
      title: "Workflow Saved",
      description: "Your workflow has been saved locally.",
    });
  };

  const exportWorkflow = () => {
    const workflow = { nodes, edges };
    const dataStr = JSON.stringify(workflow, null, 2);
    const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
    
    const exportFileDefaultName = 'workflow.json';
    
    const linkElement = document.createElement('a');
    linkElement.setAttribute('href', dataUri);
    linkElement.setAttribute('download', exportFileDefaultName);
    linkElement.click();
    
    toast({
      title: "Workflow Exported",
      description: "Workflow downloaded as JSON file.",
    });
  };

  const importWorkflow = () => {
    fileInputRef.current?.click();
  };

  const handleFileImport = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const content = e.target?.result as string;
        const workflowData = JSON.parse(content);
        
        // Check if it's an n8n workflow (has nodes array and connections)
        if (workflowData.nodes && workflowData.connections) {
          const { nodes: importedNodes, edges: importedEdges } = importN8nWorkflow(workflowData);
          setNodes(importedNodes);
          setEdges(importedEdges);
          
          toast({
            title: "n8n Workflow Imported",
            description: `Successfully imported ${importedNodes.length} nodes and ${importedEdges.length} connections.`,
          });
        } else if (workflowData.nodes && Array.isArray(workflowData.nodes)) {
          // Standard ReactFlow format
          setNodes(workflowData.nodes);
          setEdges(workflowData.edges || []);
          
          toast({
            title: "Workflow Imported",
            description: "Workflow imported successfully.",
          });
        } else {
          throw new Error("Invalid workflow format");
        }
      } catch (error) {
        toast({
          title: "Import Failed",
          description: "Failed to import workflow. Please check the file format.",
          variant: "destructive",
        });
      }
    };
    reader.readAsText(file);
    
    // Reset the input
    event.target.value = '';
  };

  const exportN8nWorkflow = () => {
    const n8nWorkflow = exportToN8nFormat(nodes, edges);
    const dataStr = JSON.stringify(n8nWorkflow, null, 2);
    const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
    
    const exportFileDefaultName = 'workflow-n8n.json';
    
    const linkElement = document.createElement('a');
    linkElement.setAttribute('href', dataUri);
    linkElement.setAttribute('download', exportFileDefaultName);
    linkElement.click();
    
    toast({
      title: "n8n Workflow Exported",
      description: "Workflow exported in n8n format.",
    });
  };

  return (
    <div className="h-screen flex bg-slate-50">
      <WorkflowSidebar />
      
      <div className="flex-1 flex flex-col">
        {/* Enhanced Toolbar */}
        <div className="h-16 border-b border-slate-200 bg-white px-6 flex items-center justify-between">
          <div className="flex items-center gap-4">
            <div className="flex items-center gap-3">
              <div className="p-2 rounded-lg bg-purple-100">
                <Sparkles className="w-5 h-5 text-purple-600" />
              </div>
              <h1 className="text-xl font-bold text-slate-900">
                Smart Courseware
              </h1>
            </div>
          </div>
          
          <div className="flex items-center gap-2">
            <Button 
              onClick={() => setNodes([])}
              variant="outline"
              size="sm"
              className="hover:scale-105 transition-transform"
            >
              <Plus className="w-4 h-4 mr-2" />
              New
            </Button>
            
            <Button 
              onClick={saveWorkflow}
              variant="outline"
              size="sm"
              className="hover:scale-105 transition-transform"
            >
              <Save className="w-4 h-4 mr-2" />
              Save
            </Button>
            
            <Button 
              onClick={exportWorkflow}
              variant="outline"
              size="sm"
              className="hover:scale-105 transition-transform"
            >
              <Download className="w-4 h-4 mr-2" />
              Export
            </Button>
            
            <Button 
              onClick={importWorkflow}
              variant="outline"
              size="sm"
              className="hover:scale-105 transition-transform"
            >
              <Upload className="w-4 h-4 mr-2" />
              Import
            </Button>
            
            <Button 
              variant="outline"
              size="sm"
              className="hover:scale-105 transition-transform"
            >
              <Settings className="w-4 h-4 mr-2" />
              Settings
            </Button>
            
             <Button 
              onClick={runWorkflow} 
              disabled={isRunning}
              className="hover:scale-105 transition-transform bg-purple-600 hover:bg-purple-700 text-white"
              size="sm"
            >
              <PlayCircle className="w-4 h-4 mr-2" />
              {isRunning ? 'Presenting...' : 'Present'}
            </Button>
            
            <Button 
              onClick={() => setShowTesting(!showTesting)}
              variant={showTesting ? "default" : "outline"}
              size="sm"
              className="hover:scale-105 transition-transform"
            >
              <TestTube className="w-4 h-4 mr-2" />
              Test
            </Button>
            
            <input
              ref={fileInputRef}
              type="file"
              accept=".json"
              onChange={handleFileImport}
              className="hidden"
            />
          </div>
        </div>

        {/* Main Content Area */}
        <div className="flex-1 flex">
          {/* Canvas */}
          <div 
            className={`flex-1 relative transition-all duration-300 ${
              isDragOver ? 'bg-primary/5 ring-2 ring-primary/20' : ''
            }`} 
            ref={reactFlowWrapper}
          >
            <ReactFlow
              nodes={nodes}
              edges={edges}
              onNodesChange={onNodesChange}
              onEdgesChange={onEdgesChange}
              onConnect={onConnect}
              onDrop={onDrop}
              onDragOver={onDragOver}
              onDragLeave={onDragLeave}
              onNodeClick={onNodeClick}
              nodeTypes={nodeTypes}
              className="courseware-canvas"
              connectionLineStyle={{ 
                stroke: '#6A5CFF',
                strokeWidth: 2.5,
                strokeDasharray: 'none'
              }}
              defaultEdgeOptions={{
                style: { 
                  stroke: '#B0B0B0',
                  strokeWidth: 2
                },
                animated: false,
                type: 'bezier'
              }}
              connectionLineType={ConnectionLineType.Bezier}
              snapToGrid={true}
              snapGrid={[20, 20]}
              fitView
              minZoom={0.1}
              maxZoom={2}
              attributionPosition="bottom-left"
            >
              <Controls className="bg-white border border-slate-200 rounded-xl" />
              <Background 
                variant={BackgroundVariant.Lines} 
                gap={20} 
                size={1}
                color="rgba(0, 0, 0, 0.03)"
                className="opacity-100"
              />
            </ReactFlow>
            
            {/* Drop Zone Indicator */}
            {isDragOver && (
              <div className="absolute inset-0 pointer-events-none flex items-center justify-center bg-primary/5 backdrop-blur-sm">
                <div className="text-center p-8 rounded-2xl bg-card/80 backdrop-blur-sm border-2 border-primary/30 shadow-xl">
                  <div className="text-2xl font-bold text-primary mb-2">Drop Here</div>
                  <div className="text-muted-foreground">Release to add the component to your flow</div>
                </div>
              </div>
            )}
          </div>
          
          {/* Properties Panel */}
          {selectedNode && (
            <PropertiesPanel 
              selectedNode={selectedNode}
              onClose={() => setSelectedNode(null)}
              onUpdate={updateNodeData}
            />
          )}
          
          {/* Testing Panel */}
          <TestingPanel 
            isVisible={showTesting}
            onToggle={() => setShowTesting(!showTesting)}
          />
        </div>
      </div>
      
      {/* Mirror Agent */}
      <MirrorAgent nodes={nodes} edges={edges} />
    </div>
  );
}

export function WorkflowCanvas() {
  return (
    <ReactFlowProvider>
      <WorkflowCanvasInner />
    </ReactFlowProvider>
  );
}